/*!
 * @file texture.cpp
 * @brief Ciało texture.hh
 */

#include "engine/basic/texture.hh"
using namespace std;

/*--------------------------------------------------------------------------*/

texture::texture() :
	gltex(), w(), h(), framebuffer(), renderbuffer() {
}

/*--------------------------------------------------------------------------*/

texture::texture(int width, int height) :
	gltex(), w(width), h(height), framebuffer(), renderbuffer() {

	glEnable(GL_TEXTURE_2D);

	glGenTextures(1, &this->gltex);
	glBindTexture(GL_TEXTURE_2D, this->gltex);

	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->w, this->h, 0, GL_RGBA,
			GL_UNSIGNED_BYTE, NULL);

	glDisable(GL_TEXTURE_2D);
}

/*--------------------------------------------------------------------------*/

texture::texture(string path) :
	gltex(), w(), h(), framebuffer(), renderbuffer() {
	this->load(path);
}

/*--------------------------------------------------------------------------*/

void texture::load(string path) {

	this->free();

	SDL_Surface *surface = IMG_Load(path.c_str());

	if (surface == NULL) {
		stringstream ss;
		ss << "Nie można wczytać tekstury z " << path;

		log::error(ss.str());

		surface = IMG_Load("pawirr/textures/replaceme.png");
		if (surface == NULL) {
			log::crash("Brak tekstury domyślnej");
		}
	}

	GLenum texture_format;
	GLint nOfColors = surface->format->BytesPerPixel;

	if (nOfColors == 4) {
		if (surface->format->Rmask == 0x000000ff)
			texture_format = GL_RGBA;
		else
			texture_format = GL_BGRA;
	} else if (nOfColors == 3) {
		if (surface->format->Rmask == 0x000000ff)
			texture_format = GL_RGB;
		else
			texture_format = GL_BGR;
	} else {

		stringstream ss;
		ss << "Zły format koloru dla tekstury w " << path;

		log::crash(ss.str());
	}

	glGenTextures(1, &this->gltex);
	glBindTexture(GL_TEXTURE_2D, this->gltex);

	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
			GL_LINEAR_MIPMAP_LINEAR );
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
			GL_LINEAR_MIPMAP_LINEAR );

	gluBuild2DMipmaps(GL_TEXTURE_2D, 4, surface->w, surface->h, texture_format,
			GL_UNSIGNED_BYTE, surface->pixels);

	const_cast<int&> (this->w) = surface->w;
	const_cast<int&> (this->h) = surface->h;

	SDL_FreeSurface(surface);
}

/*--------------------------------------------------------------------------*/

void texture::copyColorBuffer() {
	glBindTexture(GL_TEXTURE_2D, this->gltex);
	glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, this->w, this->h, 0);
}

/*--------------------------------------------------------------------------*/

void texture::bind(int i) {

	switch (i) {
	case 0: {
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, this->gltex);
		break;
	}
	case 1: {
		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_2D, this->gltex);
		glActiveTexture(GL_TEXTURE0);
		break;
	}
	case 2: {
		glActiveTexture(GL_TEXTURE2);
		glBindTexture(GL_TEXTURE_2D, this->gltex);
		glActiveTexture(GL_TEXTURE0);
		break;
	}
	case 3: {
		glActiveTexture(GL_TEXTURE3);
		glBindTexture(GL_TEXTURE_2D, this->gltex);
		glActiveTexture(GL_TEXTURE0);
		break;
	}
	case 4: {
		glActiveTexture(GL_TEXTURE4);
		glBindTexture(GL_TEXTURE_2D, this->gltex);
		glActiveTexture(GL_TEXTURE0);
		break;
	}
	case 5: {
		glActiveTexture(GL_TEXTURE5);
		glBindTexture(GL_TEXTURE_2D, this->gltex);
		glActiveTexture(GL_TEXTURE0);
		break;
	}
	case 6: {
		glActiveTexture(GL_TEXTURE6);
		glBindTexture(GL_TEXTURE_2D, this->gltex);
		glActiveTexture(GL_TEXTURE0);
		break;
	}
	case 7: {
		glActiveTexture(GL_TEXTURE7);
		glBindTexture(GL_TEXTURE_2D, this->gltex);
		glActiveTexture(GL_TEXTURE0);
		break;
	}
	default: {
	}
	}

}

/*--------------------------------------------------------------------------*/

void texture::free() {
	glDeleteTextures(1, &this->gltex);
	const_cast<int&> (this->w) = 0;
	const_cast<int&> (this->h) = 0;
}

/*--------------------------------------------------------------------------*/

texture::~texture() {
	this->free();
}

/*--------------------------------------------------------------------------*/
